package cz.data.common.mark.mybatis;

import cz.data.common.exception.DataException;
import cz.data.common.mark.mybatis.mapper.SqlServerModelMapper;
import cz.data.common.support.db.DbProperty;
import cz.data.common.support.db.DbType;
import cz.data.common.mark.mybatis.mapper.PostgreSQLModelMapper;
import cz.data.common.mark.mybatis.mapper.MySQLModelMapper;
import cz.data.common.mark.mybatis.mapper.OracleModelMapper;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import java.util.function.Consumer;
import java.util.function.Function;

public class DynamicMapperUtils {

    public static <M extends DynamicModelMapper> void consumerMapper(DbProperty profile, Consumer<M> consumer) {
        Class<M> mapperClass = (Class<M>) mapperClass(profile.getDbType());
        executeMapper(profile, mapperClass, mapper -> {
            consumer.accept(mapper);
            return null;
        });
    }

    public static <M extends DynamicModelMapper, T> T mapMapper(DbProperty profile, Function<M, T> fun) {
        Class<M> mapperClass = (Class<M>) mapperClass(profile.getDbType());
        return executeMapper(profile, mapperClass, fun);
    }

    public static <M, T> T executeMapper(DbProperty profile, Class<M> clz, Function<M, T> fun) {
        SqlSessionFactory sqlSessionFactory = sqlSessionFactory(profile);
        try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
            return fun.apply(sqlSession.getMapper(clz));
        }
    }

    public static SqlSessionFactory sqlSessionFactory(DbProperty property) {
        return MybatisFactoryUtils.sqlSessionFactory(property);
    }

    public static Class<? extends DynamicModelMapper> mapperClass(String dbType) {
        DbType type = DbType.getDbType(dbType);
        switch (type) {
            case MYSQL:
            case MARIADB:
                return MySQLModelMapper.class;
            case ORACLE:
            case ORACLE_12C:
                return OracleModelMapper.class;
            case POSTGRE_SQL:
                return PostgreSQLModelMapper.class;
            case SQL_SERVER:
            case SQL_SERVER2008:
                return SqlServerModelMapper.class;
            default:
                throw new DataException("不支持的数据类型:" + dbType);
        }
    }

}
